/*
 * ecx_esc.c
 * cezanne@clunix,com, 2005.12
 *
 * Copyright (c) 2001-2008 by Clunix Inc. All Rights Reserved.
 */

#include "config.h"

#include "ecm.h"

static ecm_uint32
get_dquot_esc_strlen(const char *c_str)
{
	ecm_uint32	n_dquot = 0, len = 0;
	const char	*p;

	if (ecm_empty_str(c_str))
		return 0;
	for (p = c_str; *p; p++) {
		if (*p == '"') {
			n_dquot++;
			len += 6;	/* &quot; */
		}
		else
			len++;
	}
	if (n_dquot == 0)
		return 0;
	return len;
}

static const char *
get_dquot_esc_str(char *esc_str, const char *c_str)
{
	const char	*p;
	char		*q;

	q = esc_str;
	for (p = c_str; *p; p++) {
		if (*p == '"') {
			q[0] = '&';
			q[1] = 'q';
			q[2] = 'u';
			q[3] = 'o';
			q[4] = 't';
			q[5] = ';';
			q += 6;
		}
		else
			*q++ = *p;
	}
	*q = '\0';
	return esc_str;
}

const char *
escape_dquot(const char *c_str, char **palloced)
{
	ecm_uint32	esc_len;

	esc_len = get_dquot_esc_strlen(c_str);
	if (esc_len == 0) {
		*palloced = NULL;
		return c_str;
	}

	*palloced = (char *)ecm_malloc(esc_len + 1);
	return get_dquot_esc_str(*palloced, c_str);
}

char *
escape_str(const char *c_str)
{
	char	*p, *head;
	char	*escstr, *temp, esc, *str;

	if (ecm_empty_str(c_str))
		return ecm_strdup(c_str);

	escstr = ecm_strdup("");
	head = p = str = ecm_strdup(c_str);
	do {
		if (isalnum((unsigned char)*p) == 0) {
			esc = *p;
			*p = '\0';
			ecm_asprintf(&temp, "%s%s_%02x", escstr, head, (unsigned char)esc);
			ecm_free(escstr);
			escstr = temp;
			head = p + 1;
		}
	} while (*++p);
	ecm_asprintf(&temp, "%s%s", escstr, head);
	ecm_free(escstr);
	escstr = temp;
	ecm_free(str);
	return escstr;
}

char *
escape_vstr(const char *fmt, va_list ap)
{
	char	*str, *escstr;

	ecm_vasprintf(&str, fmt, ap);
	escstr = escape_str(str);
	ecm_free(str);
	return escstr;
}

char *
unescape_str(const char *c_str)
{
	char	*str, *q;
	const char	*p;
	int	c;

	if (c_str == NULL)
		return NULL;

	q = str = ecm_malloc(ecm_strlen(c_str) + 1);
	p = c_str;
	while (*p) {
		if (*p == '_') {
			if (p[1] == '\0' ||
			    p[2] == '\0' ||
			    sscanf(p + 1, "%02x", &c) != 1) {
				ecm_free(str);
				return NULL;
			}
			*q++ = (char)c;
			p += 3;
		}
		else {
			*q++ = *p++;
		}
	}
	*q = '\0';
	return str;
}
